package com.ruoyi.miniapp;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.wx.WxMaConfiguration;
import com.ruoyi.common.wx.service.IWxService;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import me.chanjar.weixin.common.error.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Author caoshuhui
 * @create 2024/3/18
 */
@RestController
@RequestMapping("/wx/login")
public class WxLoginController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(WxLoginController.class);

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private RedisCache redisCache;

    @Value("${wx.miniapp.appid}")
    private String appid;

    @Autowired
    IWxService wxService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;


//    @PostMapping("/account")
//    @Transactional
//    public AjaxResult loginByAccount(@RequestBody LoginBody loginBody) throws WxErrorException {
//        String code = String.valueOf(loginBody.getAuthCode());
//        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
//        WxMaJscode2SessionResult session = null;
//        session = wxService.getUserService().getSessionInfo(code);
//        String openId = session.getOpenid();
//        // 生成令牌
//        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), openId);
//        SysUser sysUser = sysUserService.selectUserByUserName(loginBody.getUsername());
//        Map<String, Object> result = new HashMap<>();
//        result.put(Constants.TOKEN, token);
//        result.put("sysUser", sysUser);
//        return AjaxResult.success(result);
//    }

    /**
     * 登陆接口
     */
    @PostMapping("/code")
    public AjaxResult loginByCode(@RequestBody JSONObject json) {
        String code = String.valueOf(json.get("code"));
        final WxMaService wxService = WxMaConfiguration.getMaService(appid);
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);
            String openId = session.getOpenid();
            SysUser sysUser = sysUserService.selectUserByOpenId(openId);
            if (Objects.isNull(sysUser)) {
                String sessionKey = session.getSessionKey();
                //丢入缓存
                redisCache.setCacheObject("author_" + openId, sessionKey);
                this.logger.info(session.getSessionKey());
                this.logger.info(session.getOpenid());
                Map<String, Object> map = new HashMap<>();
                map.put("openId", openId);
                return AjaxResult.success(map);
            } else {
                return AjaxResult.success(loginService.appLogin(sysUser));
            }
        } catch (WxErrorException e) {
            this.logger.error(e.getMessage(), e);
            return AjaxResult.error(e.toString());
        }
    }

    @PostMapping("/testOpenId")
    public AjaxResult loginOpenId(@RequestBody JSONObject json) {
        String openId = json.getString("openId");
        SysUser sysUser = sysUserService.selectUserByOpenId(openId);
        return AjaxResult.success(loginService.appLogin(sysUser));
    }

    @PostMapping("/test")
    public AjaxResult test() {
        LoginUser user = SecurityUtils.getLoginUser();
        return AjaxResult.success(user);
    }

    @PostMapping("/phone")
    @Transactional
    public AjaxResult getPhone(@RequestBody JSONObject json
    ) {
        String openId = json.getString("openId");
        String code = json.getString("code");
        try {
            String userPhonenumber = wxService.getUserPhonenumber(code);
            SysUser sysUser = sysUserService.selectUserByPhone(userPhonenumber);
            if (Objects.nonNull(sysUser) && (StringUtils.isBlank(sysUser.getStatus()) || "1".equals(sysUser.getStatus()))) {
                throw new ServiceException("账号已停用");
            }
            if (Objects.isNull(sysUser)) {
                return AjaxResult.error(500, "非目标用户，无法登陆");
            } else {
                sysUserService.updateOpenId(sysUser.getUserId(), openId);
                return AjaxResult.success(loginService.appLogin(sysUser));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error();
    }

    @Transactional
    @PostMapping("/testPhone")
    public AjaxResult Phone(@RequestBody JSONObject json) {
        String phoneNumber = json.getString("phone");
        String openId = json.getString("openId");
        SysUser sysUser = sysUserService.selectUserByPhone(phoneNumber);
        if (Objects.isNull(sysUser)) {
            return AjaxResult.error(500, "非目标用户，无法登陆");
        } else {
            sysUserService.updateOpenId(sysUser.getUserId(), openId);
            return AjaxResult.success(loginService.appLogin(sysUser));
        }
    }


    @PostMapping("/logout")
    public AjaxResult logout() {
        sysUserService.updateOpenId(SecurityUtils.getUserId(), " ");
        return AjaxResult.success();
    }

    @PostMapping("/userAndPassword")
    public AjaxResult login(@RequestBody LoginBody loginBody) {

        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), "app",
                loginBody.getUuid());
        Map<String, Object> result = new HashMap<>();

        SysUser sysUser = sysUserService.selectUserByUserName(loginBody.getUsername());
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(sysUser.getUserId());
        loginUser.setDeptId(sysUser.getDeptId());
        loginUser.setUser(sysUser);
        sysUserService.setRoleBelong(loginUser.getUser());
        result.put(Constants.TOKEN, token);
        result.put("sysUser", loginUser);
        result.put("permission", permissionService.getMenuPermission(loginUser.getUser()));
        return AjaxResult.success(result);
    }

    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(String oldPassword, String newPassword) {
        LoginUser loginUser = getLoginUser();
        String userName = loginUser.getUsername();
        String password = loginUser.getPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password)) {
            return error("修改密码失败，旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password)) {
            return error("新密码不能与旧密码相同");
        }
        newPassword = SecurityUtils.encryptPassword(newPassword);
        if (sysUserService.resetUserPwd(userName, newPassword) > 0) {
            // 更新缓存用户密码
            loginUser.getUser().setPassword(newPassword);
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改密码异常，请联系管理员");
    }
}
